//
//  Waypoint.m
//  Henry
//
//  Created by Ron Olson on 3/10/10.
//  Copyright 2010 Keep Bertha Surfin. All rights reserved.
//

#import "Waypoint.h"


@implementation Waypoint

@synthesize wptName;
@synthesize wptDescription;
@synthesize latitude;
@synthesize longitude;

-(id)init
{
	[self dealloc];
	@throw [NSException exceptionWithName:@"WrongInitcall" reason:@"This class must be initialized with all the parameters" userInfo:nil];
	return nil;
}

/*
 * @param latitude
 *            (in Decimal degrees e.g. 41.89637)
 * @param longitude
 *            (in Decimal degrees e.g. -87.64412)
 */
-(id)initWithName:(NSString*)theName description:(NSString*)theDescription latitude:(double)lat longitude:(double)lon
{
	if (![super init])
		return nil;
	
	wptName = [theName copy];
	wptDescription = [theDescription copy];
	latitude = lat;
	longitude = lon;
	
	return self;
}

-(NSString*)getFormattedWPForGoogleMaps
{
	/* The format is name@lat,long */
	return [NSString stringWithFormat:@"%@@%f,%f", wptName, latitude, longitude];
}

/**
 * Returns the distance between this and the argument waypoint Based on the
 * formulas from {@link http://williams.best.vwh.net/avform.htm}
 * <p/>
 * 
 * It's not not as optimized as I suppose it could be, but I left it this
 * way so that I could debug it :)
 * 
 * @param waypoint
 * @return distance in radians
 */
-(double)distanceFrom:(Waypoint*)otherWaypoint
{
	double thisLatRads = latitude * PI / 180.0;
	double thisLongRads = longitude * PI / 180.0;
	
	double otherLatRads = otherWaypoint.latitude * PI / 180.0;
	double otherLongRads = otherWaypoint.longitude * PI / 180.0;
	
	double distance = 3963.0 * acos(sin(thisLatRads) * sin(otherLatRads) + cos(thisLatRads) * cos(otherLatRads) * cos(otherLongRads - thisLongRads));
									
	return distance;
}

/**
 * Compares the current waypoint to two others and indicates which one it is
 * closest to. 0 = all waypoints are the same. -1 means left side is closer,
 * 1 = right side is closer
 * 
 * @param leftSideWaypoint
 * @param rightSideWaypoint
 */
-(int)isCloserTo:(Waypoint*)leftSideWaypoint orTo:(Waypoint*)rightSideWaypoint
{
	double leftRads = [self distanceFrom:leftSideWaypoint];
	double rightRads = [self distanceFrom:rightSideWaypoint];
	
	if (leftRads < rightRads)
		return -1;
	else if (leftRads > rightRads)
		return 1;
	
	return 0;
}

/**
 * Given a list of waypoints, determines which waypoint one in the list is
 * closest to this waypoint
 * 
 * @param list
 *            of {@link Waypoint} objects
 * @return {@link Waypoint} object that is closest to this waypoint
 */
-(Waypoint*)isClosestTo:(NSArray*)waypoints
{
	Waypoint *closestWP = nil;

	for(Waypoint *currentWP in waypoints)
	{
		if (closestWP == nil)
			closestWP = currentWP;
		else 
		{
			if ([self isCloserTo:closestWP orTo:currentWP] == 1)
				closestWP = currentWP;
		}
	}
	
	return closestWP;
}

@end
